using UnityEngine;
using System.Collections.Generic;

namespace Utility
{
    public class ObjectPool : MonoBehaviour
    {
        // 对象池子项定义
        [System.Serializable]
        public class Pool
        {
            public string tag;
            public GameObject prefab;
            public int size;
        }

        // 单例模式
        private static ObjectPool instance;
        public static ObjectPool Instance
        {
            get
            {
                if (instance == null)
                {
                    GameObject go = new GameObject("ObjectPool");
                    instance = go.AddComponent<ObjectPool>();
                    DontDestroyOnLoad(go);
                }
                return instance;
            }
        }

        // 对象池集合
        public List<Pool> pools;
        private Dictionary<string, Queue<GameObject>> poolDictionary = new Dictionary<string, Queue<GameObject>>();

        private void Awake()
        {
            if (instance == null)
            {
                instance = this;
                DontDestroyOnLoad(gameObject);
                
                // 初始化所有对象池
                InitializePools();
            }
            else if (instance != this)
            {
                Destroy(gameObject);
            }
        }

        // 初始化所有对象池
        private void InitializePools()
        {
            if (pools == null || pools.Count == 0)
            {
                Debug.LogWarning("No pools defined for ObjectPool.");
                return;
            }

            foreach (Pool pool in pools)
            {
                if (pool.prefab == null)
                {
                    Debug.LogError("ObjectPool: Prefab is null for tag " + pool.tag);
                    continue;
                }

                Queue<GameObject> objectPool = new Queue<GameObject>();

                for (int i = 0; i < pool.size; i++)
                {
                    GameObject obj = Instantiate(pool.prefab);
                    obj.SetActive(false);
                    obj.transform.SetParent(transform);
                    objectPool.Enqueue(obj);
                }

                if (poolDictionary.ContainsKey(pool.tag))
                {
                    Debug.LogWarning("ObjectPool: Pool with tag " + pool.tag + " already exists. Overwriting.");
                    poolDictionary[pool.tag] = objectPool;
                }
                else
                {
                    poolDictionary.Add(pool.tag, objectPool);
                }
            }
        }

        // 从对象池获取对象
        public GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation)
        {
            if (!poolDictionary.ContainsKey(tag))
            {
                Debug.LogWarning("ObjectPool: Pool with tag " + tag + " doesn't exist.");
                return null;
            }

            Queue<GameObject> pool = poolDictionary[tag];
            
            if (pool.Count == 0)
            {
                Debug.LogWarning("ObjectPool: Pool with tag " + tag + " is empty.");
                
                // 查找对应的预制体以创建新对象
                GameObject prefab = null;
                foreach (Pool p in pools)
                {
                    if (p.tag == tag)
                    {
                        prefab = p.prefab;
                        break;
                    }
                }
                
                if (prefab != null)
                {
                    GameObject obj = Instantiate(prefab, position, rotation);
                    return obj;
                }
                
                return null;
            }

            GameObject objectToSpawn = pool.Dequeue();
            
            if (objectToSpawn == null)
            {
                return SpawnFromPool(tag, position, rotation); // 递归尝试获取下一个对象
            }

            objectToSpawn.SetActive(true);
            objectToSpawn.transform.position = position;
            objectToSpawn.transform.rotation = rotation;

            return objectToSpawn;
        }

        // 返回对象到池中 - 标签版本
        public void ReturnToPool(string tag, GameObject obj)
        {
            if (obj == null)
            {
                Debug.LogWarning("ObjectPool: Attempted to return null object to pool.");
                return;
            }

            if (!poolDictionary.ContainsKey(tag))
            {
                Debug.LogWarning("ObjectPool: Pool with tag " + tag + " doesn't exist.");
                Destroy(obj);
                return;
            }

            obj.SetActive(false);
            obj.transform.SetParent(transform);
            poolDictionary[tag].Enqueue(obj);
        }

        // 返回对象到池中 - 对象版本
        public void ReturnToPool(GameObject obj)
        {
            if (obj == null) return;

            string tag = obj.tag;
            ReturnToPool(tag, obj);
        }

        // 清空特定池
        public void ClearPool(string tag)
        {
            if (poolDictionary.ContainsKey(tag))
            {
                Queue<GameObject> pool = poolDictionary[tag];
                while (pool.Count > 0)
                {
                    GameObject obj = pool.Dequeue();
                    if (obj != null)
                    {
                        Destroy(obj);
                    }
                }
                poolDictionary.Remove(tag);
            }
        }

        // 清空所有池
        public void ClearAllPools()
        {
            foreach (var pool in poolDictionary.Values)
            {
                while (pool.Count > 0)
                {
                    GameObject obj = pool.Dequeue();
                    if (obj != null)
                    {
                        Destroy(obj);
                    }
                }
            }
            poolDictionary.Clear();
        }

        public void InitializePoolsManually()
        {
            if (pools == null || pools.Count == 0)
            {
                Debug.LogWarning("No pools defined for ObjectPool.");
                return;
            }

            poolDictionary.Clear(); // 清空已有池

            foreach (Pool pool in pools)
            {
                if (pool.prefab == null)
                {
                    Debug.LogError("ObjectPool: Prefab is null for tag " + pool.tag);
                    continue;
                }

                Debug.Log("创建对象池: " + pool.tag + "，大小: " + pool.size);
                
                Queue<GameObject> objectPool = new Queue<GameObject>();

                for (int i = 0; i < pool.size; i++)
                {
                    GameObject obj = Instantiate(pool.prefab);
                    obj.SetActive(false);
                    obj.transform.SetParent(transform);
                    objectPool.Enqueue(obj);
                }

                if (poolDictionary.ContainsKey(pool.tag))
                {
                    Debug.LogWarning("ObjectPool: Pool with tag " + pool.tag + " already exists. Overwriting.");
                    poolDictionary[pool.tag] = objectPool;
                }
                else
                {
                    poolDictionary.Add(pool.tag, objectPool);
                }
            }
            
            Debug.Log("所有对象池初始化完成，共 " + poolDictionary.Count + " 个池");
        }
    }
}